﻿Imports System.Text.RegularExpressions
Imports System.Text
Imports System.Collections.ObjectModel
Imports System.Reflection

''' <summary>
''' エンティティアーカイバー
''' </summary>
''' <remarks></remarks>
Friend NotInheritable Class EntityArchiver

    Private Sub New()
    End Sub

    ''' <summary>
    ''' エンティティアーカイブを作成します
    ''' </summary>
    ''' <param name="instance"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared Function Create(instance As Object) As IEntityArchive
        If instance Is Nothing Then Return Nothing

        If TypeOf instance Is ICollection Then
            Dim arch = EntityArchiver.CreateCollectionArchive(instance)
            Return arch
        Else
            Dim arch = EntityArchiver.CreateItemArchive(instance, instance.GetType)
            Return arch
        End If
    End Function

    ''' <summary>
    ''' コレクションアーカイブを作成します
    ''' </summary>
    ''' <param name="instance"></param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CreateCollectionArchive(instance As Object) As CollectionEntityArchive
        Dim arch As New CollectionEntityArchive

        '現インスタンスのコレクションを取得する
        Dim lst = DirectCast(instance, ICollection)

        '現インスタンスにあるコレクションアイテムを全てアーカイブする
        For Each item In lst
            Dim ia As ItemEntityArchive = DirectCast(EntityArchiver.Create(item), ItemEntityArchive)
            arch.Container.Archives.Add(ia.Key, ia)
        Next

        Return arch
    End Function

    ''' <summary>
    ''' アイテムアーカイブを作成します
    ''' </summary>
    ''' <param name="instance">インスタンス</param>
    ''' <param name="t">検査対象型</param>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Private Shared Function CreateItemArchive(instance As Object, t As Type) As ItemEntityArchive
        If t Is Nothing Then Return Nothing

        Dim arch As New ItemEntityArchive
        arch.EntityKey = KeyGenerator.Generate(instance)
        arch.ClassType = t

        Dim def = t.ToEntityDefinition

        '基底アーカイブ
        arch.BaseArchive = EntityArchiver.CreateItemArchive(instance, def.BaseEntityType) '再帰呼び出し

        'プロパティアーカイブ
        For Each item In PropertyArchiver.Create(instance, t)
            item.Owner = arch

            Dim c = TryCast(item, LiteralPropertyArchive)
            If c IsNot Nothing Then
                arch.ItemArchives.Add(item.Key, c)
            Else
                arch.CollectionArchives.Add(item.Key, DirectCast(item, CollectionPropertyArchive))
            End If
        Next

        Return arch
    End Function
End Class